﻿/*
 * Сделано в SharpDevelop.
 * Пользователь: maxxadm
 * Дата: 10/04/2012
 * Время: 20:43
 * 
 * Для изменения этого шаблона используйте Сервис | Настройка | Кодирование | Правка стандартных заголовков.
 */
using System;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.ComponentModel;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using Hammock;

namespace jellybird.core
{
	public class TwMediaHelper
	{
		/*
		public static bool SupportsUrl(string url)
		{
			bool ret = false;

			if (url.StartsWith(URL_TWITPIC, StringComparison.OrdinalIgnoreCase))
				return true;

			if (url.StartsWith(URL_YFROG, StringComparison.OrdinalIgnoreCase))
				return true;
			
			if(url.StartsWith(URL_INSTAGRAM,StringComparison.OrdinalIgnoreCase))
				return true;

			if (url.StartsWith(URL_YOUTUBE_1, StringComparison.OrdinalIgnoreCase))
				return true;

			if (url.StartsWith(URL_YOUTUBE_2, StringComparison.OrdinalIgnoreCase))
				return true;
			
			return ret;
		}
		 */

		/// <summary>
		/// set callbacks etc...
		/// </summary>
		/// <param name="image"></param>
		private static void prepare_bitmap_image(BitmapImage image)
		{
			/*
			 * http://code.logos.com/blog/2010/07/exceptions_thrown_by_bitmapimage_and_bitmapframe.html
			 */
			image.CreateOptions = BitmapCreateOptions.IgnoreColorProfile;

			image.DecodeFailed += (s, e) =>
			{
				#if DEBUG
				Helper.OnDebugMessage
					(string.Format("Decode failed {0}, {1}", (s as BitmapImage).UriSource, e.ErrorException.Message));
				#endif
			};

			image.DownloadFailed += (s, e) =>
			{
				#if DEBUG
				Helper.OnDebugMessage
					(string.Format("Download failed {0}, {1}", (s as BitmapImage).UriSource, e.ErrorException.Message));
				#endif
			};

			image.DownloadCompleted += (s, e) =>
			{
				#if DEBUG
				Helper.OnDebugMessage
					(string.Format("Complete download and freeze {0}", (s as BitmapImage).UriSource));
				#endif

				(s as BitmapImage).Freeze();
			};
		}

		private const string YOUTUBE_API_VERSION = "2";
		private const int DEFAULT_MAX_WIDTH = 360;
		private const int DEFAULT_MAX_HEIGHT = 360;
		public const string URL_TWITPIC = @"http://twitpic.com/";
		public const string URL_YFROG = @"http://yfrog.com/";
		public const string URL_INSTAGRAM=@"http://instagr.am/";
		public const string URL_YOUTUBE_1 = @"http://www.youtube.com";
		public const string URL_YOUTUBE_2 = @"http://youtu.be";

		/*
		 * youtube:
		 * https://developers.google.com/gdata/docs/json
		 * json in google api
		 * 
		 * https://developers.google.com/youtube/2.0/developers_guide_protocol_video_entries
		 * retrieving data for single video
		 * 
		 * https://developers.google.com/youtube/2.0/developers_guide_protocol_understanding_video_feeds?hl=ru#Understanding_Feeds_and_Entries
		 * example of video info output
		 */

		/*
		 * yfrog: http://twitter.yfrog.com/page/api#a6
		 * Yfrog api - xml output
		 */



		public static string GetVideoIdYoutube
			(string url)
		{
			if (string.IsNullOrWhiteSpace(url))
				return null;

			Uri uri = new Uri(url);
			if (url.StartsWith(URL_YOUTUBE_1, StringComparison.OrdinalIgnoreCase))
			{
				//long url like
				//http://www.youtube.com/watch?v=yhLiqCdFyQs
				string query = uri.Query;
				if (query.StartsWith("?", StringComparison.OrdinalIgnoreCase))
				{
					query = query.Substring(1);
				}
				if (query.Length == 0)
					return null;
				string[] query_parts = query.Split('&');
				for (int ind = 0; ind < query_parts.Length; ind++)
				{
					string[] key_value=query_parts[ind].Split('=');
					if((key_value.Length==2)&&(key_value[0].Equals("v")))
					{
						return key_value[1];
					}
				}
			}
			else if (url.StartsWith(URL_YOUTUBE_2))
			{
				//short url form like
				//http://youtu.be/yhLiqCdFyQs
				//id во втором сегменте
				if (uri.Segments.Length > 1)
				{
					return uri.Segments[1];
				}
			}
			return null;
		}

		public static JObject GetMediaInfoInstagram
			(string url)
		{
			//http://instagram.com/developer/embedding/

			if (string.IsNullOrWhiteSpace(url))
				return null;

			RestClient client = new RestClient()
			{
				Authority = @"http://api.instagram.com",
				FollowRedirects = true,
				Method = Hammock.Web.WebMethod.Get
			};

			RestRequest request = new RestRequest()
			{
				Path = @"oembed"
			};

			request.AddParameter("url", url);

			RestResponse response = null;
			try
			{
				response = client.Request(request);
				JObject ret = JObject.Parse(response.Content);
				return ret;
			}
			finally
			{
				if (response != null)
					response.Dispose();
			}
		}

		public static XDocument GetMediaInfoYoutube
			(string video_id)
		{
			if (string.IsNullOrWhiteSpace(video_id))
				return null;

			RestClient client = new RestClient()
			{
				Authority = @"https://gdata.youtube.com",
				FollowRedirects = true,
				Method = Hammock.Web.WebMethod.Get
			};

			RestRequest request = new RestRequest()
			{
				Path = @"feeds/api/videos/" + video_id
			};

			request.AddParameter("v", YOUTUBE_API_VERSION);

			RestResponse response = null;
			try
			{
				response = client.Request(request);
				XDocument ret = XDocument.Load(response.ContentStream);

				/*
				 * example:
				XNamespace media_ns = ret.Root.GetNamespaceOfPrefix("media");
				IEnumerable<XElement> elem_enum =
					(from el in ret.Descendants(media_ns + "thumbnail") select el);
				foreach (var elem in elem_enum)
				{
					string s = elem.Value;
					string url = elem.Attribute("url").Value;
				}
				 */
				
				return ret;
			}
			finally
			{
				if (response != null)
					response.Dispose();
			}
		}

		public static XDocument GetMediaInfoYfrog
			(Uri uri)
		{
			return GetMediaInfoYfrog(GetMediaIdFromUrlYfrog(uri));
		}
		
		public static string GetMediaIdFromUrlYfrog(Uri uri)
		{
			return uri.Segments[1];
		}

		public static XDocument GetMediaInfoYfrog
			(string image_id)
		{
			if (string.IsNullOrWhiteSpace(image_id))
				return null;

			RestClient client = new RestClient()
			{
				Authority = @"http://yfrog.com",
				FollowRedirects = true,
				Method = Hammock.Web.WebMethod.Get
			};

			RestRequest request = new RestRequest()
			{
				Path=@"api/xmlInfo"
			};

			request.AddParameter("path", image_id);
			RestResponse response = null;
			try
			{
				response=client.Request(request);
//				XmlDocument ret=new XmlDocument();
//				ret.Load(response.ContentStream);
				
				XDocument ret=XDocument.Load(response.ContentStream);
				
				/*
				XNamespace aw=ret.Root.GetDefaultNamespace();
				
				int height=
					int.Parse((string)(from el in ret.Descendants(aw+"height") select el).First());
				 */
				
				return ret;
			}
			finally
			{
				if(response!=null)
					response.Dispose();
			}
		}
		
		public static JObject GetMediaInfoTwitpic
			(Uri uri)
		{
			return GetMediaInfoTwitpic(GetMediaIdFromUrlTwitpic(uri));
		}

		public static string GetMediaIdFromUrlTwitpic
			(string url)
		{
			return GetMediaIdFromUrlTwitpic(new Uri(url, UriKind.Absolute));
		}

		public static string GetMediaIdFromUrlTwitpic
			(Uri uri)
		{
			if (uri.Segments.Length > 1)
			{
				return uri.Segments[1];
			}
			else
			{
				return null;
			}
		}
		
		/// <summary>
		/// Return image info in json format.
		/// About fields: http://dev.twitpic.com/docs/2/media_show
		/// </summary>
		/// <param name="image_id"></param>
		/// <returns></returns>
		public static JObject GetMediaInfoTwitpic
			(string image_id)
		{
			if (string.IsNullOrWhiteSpace(image_id))
				return null;

			RestClient client = new RestClient()
			{
				Authority = @"http://api.twitpic.com",
				FollowRedirects = true,
				Method = Hammock.Web.WebMethod.Get,
				VersionPath = "2"
			};

			RestRequest request = new RestRequest()
			{
				Path=@"media/show.json"
			};

			request.AddParameter("id", image_id);
			RestResponse response = null;
			try
			{
				response = client.Request(request);
				if (response.StatusCode == System.Net.HttpStatusCode.OK)
				{
					JObject ret = JObject.Parse(response.Content);
					return ret;
				}
				else
				{
					throw new ApplicationException(string.Format("Failed request '{0}' Status={1}", response.RequestUri, response.StatusCode));
				}
			}
			finally
			{
				if (response != null)
					response.Dispose();
			}
		}

		

		private static bool get_thumb_url
			(string expanded_url,
			 int max_width,
			 int max_height,
			 out string thumb_url,
			 out int width,
			 out int height)
		{
			thumb_url = null;
			width = 0;
			height = 0;

			Uri expand_uri = new Uri(expanded_url, UriKind.Absolute);
			Uri thumb_uri;

			if (expanded_url.StartsWith(URL_TWITPIC, StringComparison.OrdinalIgnoreCase))
			{
				
				//во втором сегменте будет id каринки
				/*
				 * У twitpic два варианта:
				 * 150x150	thumb
				 * 75x75	mini
				 * 600x...	large
				 * http://dev.twitpic.com/docs/thumbnails/
				 * или full
				 */
				if (600 < max_width)
				{
					//покажем large
					thumb_uri = new Uri(expand_uri, @"show/large/" + expand_uri.Segments[1]);
					thumb_url = thumb_uri.AbsoluteUri;
					width = 600;
					return true;
				}
				if (150 < max_width)
				{
					thumb_uri = new Uri(expand_uri, @"show/thumb/" + expand_uri.Segments[1]);
					thumb_url = thumb_uri.AbsoluteUri;
					width = 150;
					height = 150;
					return true;
				}
				if (75 < max_width)
				{
					thumb_uri = new Uri(expand_uri, @"show/mini/" + expand_uri.Segments[1]);
					thumb_url = thumb_uri.AbsoluteUri;
					width = 75;
					height = 75;
					return true;
				}
			}
			else if (expanded_url.StartsWith(URL_YFROG, StringComparison.OrdinalIgnoreCase))
			{
				/*
				 * yfrog
				 * 100x100	small
				 * 480x480	iphone
				 * 640x480	medium (only photos)
				 * 
				 * http://twitter.yfrog.com/page/api#a5
				 * 
				 */
				if (640 < max_width)
				{
					thumb_uri = new Uri(expand_uri.Scheme+Uri.SchemeDelimiter+expand_uri.Authority+expand_uri.Segments[0]+expand_uri.Segments[1] + ":medium");
					thumb_url = thumb_uri.AbsoluteUri;
					width = 640;
//					height = 480;
					return true;
				}
				if (480 < max_width)
				{
					thumb_uri = new Uri(expand_uri.Scheme+Uri.SchemeDelimiter+expand_uri.Authority+expand_uri.Segments[0]+expand_uri.Segments[1] + ":iphone");
					thumb_url = thumb_uri.AbsoluteUri;
					width = 480;
					height = 480;
					return true;
				}
				thumb_uri = new Uri(expand_uri.Scheme+Uri.SchemeDelimiter+expand_uri.Authority+expand_uri.Segments[0]+expand_uri.Segments[1] + ":small");
				thumb_url = thumb_uri.AbsoluteUri;
				width = 100;
				height = 100;
				return true;
			}
			else if(expanded_url.StartsWith(URL_INSTAGRAM,StringComparison.OrdinalIgnoreCase))
			{
				/*
				 * instagram:
				 * t	150x150
				 * m	306x306
				 * l	612x612
				 * 
				 */
				if(612<max_width)
				{
					thumb_uri = new Uri(expand_uri, @"media/?size=l");
					thumb_url = thumb_uri.AbsoluteUri;
					width = 612;
					height = 612;
					return true;
				}
				if(306<max_width)
				{
					thumb_uri = new Uri(expand_uri, @"media/?size=m");
					thumb_url = thumb_uri.AbsoluteUri;
					width = 306;
					height = 306;
					return true;
				}
				thumb_uri = new Uri(expand_uri, @"media/?size=t");
				thumb_url = thumb_uri.AbsoluteUri;
				width = 150;
				height = 150;
				return true;
			}
			//fallback
			//возвращаем исходный url
			thumb_url = expanded_url;
			width = 0;
			height = 0;
			return true;


			return false;
		}

		public static BitmapImage RetrieveImage(string url,int width=0,int height=0)
		{
			BitmapImage ret = new BitmapImage();

			ret.BeginInit();

			prepare_bitmap_image(ret);
			if (height != 0)
				ret.DecodePixelHeight = height;
			if (width != 0)
				ret.DecodePixelWidth = width;
			ret.UriSource = new Uri(url, UriKind.Absolute);

			ret.EndInit();

			return ret;
		}
		
		public static BitmapImage RetrieveThumbnail
			(string expanded_url = null,
			 int max_width = DEFAULT_MAX_WIDTH,
			 int max_height = DEFAULT_MAX_HEIGHT)
		{
			if (string.IsNullOrWhiteSpace(expanded_url))
				return null;

			string thumb_url;
			int thumb_width;
			int thumb_height;
			if (!get_thumb_url
			    (expanded_url,
			     max_width,
			     max_height,
			     out thumb_url,
			     out thumb_width,
			     out thumb_height))
				return null;

			BitmapImage ret = new BitmapImage();

			ret.BeginInit();

			prepare_bitmap_image(ret);
			if (thumb_height != 0)
				ret.DecodePixelHeight = thumb_height;
			if (thumb_width != 0)
				ret.DecodePixelWidth = thumb_width;
			else
				ret.DecodePixelWidth = max_width - 10;
			ret.UriSource = new Uri(thumb_url, UriKind.Absolute);

			ret.EndInit();

			return ret;
		}

		public static BitmapImage RetrieveThumbnail
			(TwEntityMedia entity_media = null,
			 int max_width = DEFAULT_MAX_WIDTH,
			 int max_height=DEFAULT_MAX_HEIGHT)
		{
			if (entity_media == null)
				return null;

			BitmapImage ret = new BitmapImage();
			ret.BeginInit();

			prepare_bitmap_image(ret);

			int height_actual = 0;
			int width_actual = 0;
			string url_actual = string.Empty;

			//detect size
			if ((entity_media.Sizes.Large.Width < max_width) && (entity_media.Sizes.Large.Height < max_height))
			{
				height_actual = entity_media.Sizes.Large.Height;
				width_actual = entity_media.Sizes.Large.Width;
				url_actual = entity_media.MediaUrlHttps + ":large";
			}
			else if ((entity_media.Sizes.Medium.Width < max_width) && (entity_media.Sizes.Large.Height < max_height))
			{
				height_actual = entity_media.Sizes.Medium.Height;
				width_actual = entity_media.Sizes.Medium.Width;
				url_actual = entity_media.MediaUrlHttps + ":medium";
			}
			else if ((entity_media.Sizes.Small.Width < max_width) && (entity_media.Sizes.Small.Height < max_height))
			{
				height_actual = entity_media.Sizes.Small.Height;
				width_actual = entity_media.Sizes.Small.Width;
				url_actual = entity_media.MediaUrlHttps + ":small";
			}
			else
			{
				//если ничего не подошло - самый малый размер будем брать
				double width_koef = (double)entity_media.Sizes.Thumb.Width / (double)max_width;
				double height_koef = (double)entity_media.Sizes.Thumb.Height / (double)max_height;
				double actual_koef = Math.Max(width_koef, height_koef);
				if (actual_koef > 1.0)
				{
					//если по одному из измерений не влезает - уменьшаем до максимально возможного
					width_actual = (int)((double)entity_media.Sizes.Thumb.Width / actual_koef);
					height_actual = (int)((double)entity_media.Sizes.Thumb.Height / actual_koef);
				}
				else
				{
					//а если лезает ничего не делаем
					width_actual = entity_media.Sizes.Thumb.Width;
					height_actual = entity_media.Sizes.Thumb.Height;
				}
				url_actual = entity_media.MediaUrlHttps + ":thumb";
			}

			ret.DecodePixelHeight = height_actual;
			ret.DecodePixelWidth = width_actual;
			ret.UriSource = new Uri(url_actual, UriKind.Absolute);
			ret.EndInit();

			return ret;
		}

	}


	public class TwMediaElement
	{
		private TwMediaElement() { }

		public static TwMediaElement FromEntityMedia(TwEntityMedia entity_media)
		{
			TwMediaElement ret = null;

			if (entity_media != null)
			{
				ret = new TwMediaElement();
				ret.m_entity_media = entity_media;
				ret.m_NavigateUrl = entity_media.ExpandedUrl;
			}

			return ret;
		}

		public static TwMediaElement FromEntityUrl(TwEntityUrl entity_url)
		{
			TwMediaElement ret = null;

			if (entity_url != null)
			{
				

				ret = new TwMediaElement();
				ret.m_entity_url = entity_url;
				ret.m_NavigateUrl = entity_url.ExpandedUrl;
			}

			return ret;
		}

		private bool need_update_thumb = true;
		private string m_NavigateUrl;
		private TwEntityMedia m_entity_media = null;
		private TwEntityUrl m_entity_url = null;

		public string NavigateUrl
		{
			get { return m_NavigateUrl; }
		}
		

		public TwEntityMedia EntityMedia
		{
			get { return m_entity_media; }
		}

		public TwEntityUrl EntityUrl
		{
			get { return m_entity_url; }
		}

		public BitmapImage GetThumbnail(int max_width, int max_height)
		{
			BitmapImage ret = null;

			return ret;
			/*
			if ((m_Thumb == null) || (need_update_thumb))
			{
				if (EntityMedia != null)
					m_Thumb = TwMediaHelper.RetrieveThumbnail(EntityMedia, PreferredWidth);
				if (EntityUrl != null)
					m_Thumb = TwMediaHelper.RetrieveThumbnail(EntityUrl.ExpandedUrl, PreferredWidth);
				m_Thumb.DownloadCompleted +=
					(s, e) => On_property_changed(new PropertyChangedEventArgs(null));
				need_update_thumb = false;
			}
			return m_Thumb;
			 */
		}
	}
}
